package handlers

import (
	"net/http"
	"strconv"

	"github.com/cynhard/ticket-system/internal/models"
	"github.com/cynhard/ticket-system/internal/services"
	"github.com/gin-gonic/gin"
)

// TicketHandler 工单处理器
type TicketHandler struct {
	ticketService services.TicketService
}

// NewTicketHandler 创建工单处理器
func NewTicketHandler(ticketService services.TicketService) *TicketHandler {
	return &TicketHandler{
		ticketService: ticketService,
	}
}

// CreateTicket 创建工单
func (h *TicketHandler) CreateTicket(c *gin.Context) {
	var req struct {
		Title       string `json:"title" binding:"required,min=5,max=255"`
		Description string `json:"description" binding:"required"`
		Priority    string `json:"priority" binding:"omitempty,oneof=low medium high"`
	}

	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{
			"code":    400,
			"message": "请求参数错误: " + err.Error(),
		})
		return
	}

	userID, _ := c.Get("userID")
	ticket, err := h.ticketService.CreateTicket(req.Title, req.Description, req.Priority, userID.(uint))
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"code":    500,
			"message": "创建工单失败: " + err.Error(),
		})
		return
	}

	c.JSON(http.StatusCreated, gin.H{
		"code":    201,
		"message": "工单创建成功",
		"data":    ticket,
	})
}

// GetTicket 获取工单详情
func (h *TicketHandler) GetTicket(c *gin.Context) {
	ticketIDStr := c.Param("id")
	ticketID, err := strconv.ParseUint(ticketIDStr, 10, 32)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{
			"code":    400,
			"message": "无效的工单ID",
		})
		return
	}

	ticket, err := h.ticketService.GetTicketByID(uint(ticketID))
	if err != nil {
		c.JSON(http.StatusNotFound, gin.H{
			"code":    404,
			"message": "工单不存在: " + err.Error(),
		})
		return
	}

	// 检查权限：只有工单创建者、分配者或者管理员/客服可以查看详情
	userID, _ := c.Get("userID")
	userRole, _ := c.Get("role")
	
	isCreator := ticket.CreatorID == userID.(uint)
	isAssignee := ticket.AssigneeID != nil && *ticket.AssigneeID == userID.(uint)
	isAdmin := userRole == models.RoleAdmin
	isSupport := userRole == models.RoleSupport

	if !isCreator && !isAssignee && !isAdmin && !isSupport {
		c.JSON(http.StatusForbidden, gin.H{
			"code":    403,
			"message": "您没有权限查看此工单",
		})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"code":    200,
		"message": "获取工单成功",
		"data":    ticket,
	})
}

// ListTickets 获取工单列表
func (h *TicketHandler) ListTickets(c *gin.Context) {
	// 获取分页参数
	page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
	pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "10"))
	status := c.Query("status")

	// 限制页码和每页数量
	if page < 1 {
		page = 1
	}
	if pageSize < 1 || pageSize > 100 {
		pageSize = 10
	}

	// 验证状态参数
	if status != "" && status != models.StatusOpen && status != models.StatusAssigned && 
	   status != models.StatusResolved && status != models.StatusClosed {
		c.JSON(http.StatusBadRequest, gin.H{
			"code":    400,
			"message": "无效的状态参数",
		})
		return
	}

	// 获取工单列表
	tickets, total, err := h.ticketService.ListTickets(page, pageSize, status)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"code":    500,
			"message": "获取工单列表失败: " + err.Error(),
		})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"code":    200,
		"message": "获取工单列表成功",
		"data": gin.H{
			"tickets":    tickets,
			"total":      total,
			"page":       page,
			"page_size":  pageSize,
			"total_page": (total + int64(pageSize) - 1) / int64(pageSize),
		},
	})
}

// ListMyTickets 获取我的工单列表
func (h *TicketHandler) ListMyTickets(c *gin.Context) {
	// 获取分页参数
	page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
	pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "10"))

	// 限制页码和每页数量
	if page < 1 {
		page = 1
	}
	if pageSize < 1 || pageSize > 100 {
		pageSize = 10
	}

	userID, _ := c.Get("userID")
	tickets, total, err := h.ticketService.ListUserTickets(userID.(uint), page, pageSize)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"code":    500,
			"message": "获取我的工单列表失败: " + err.Error(),
		})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"code":    200,
		"message": "获取我的工单列表成功",
		"data": gin.H{
			"tickets":    tickets,
			"total":      total,
			"page":       page,
			"page_size":  pageSize,
			"total_page": (total + int64(pageSize) - 1) / int64(pageSize),
		},
	})
}

// ListAssignedTickets 获取分配给我的工单列表
func (h *TicketHandler) ListAssignedTickets(c *gin.Context) {
	// 获取分页参数
	page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
	pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "10"))

	// 限制页码和每页数量
	if page < 1 {
		page = 1
	}
	if pageSize < 1 || pageSize > 100 {
		pageSize = 10
	}

	userID, _ := c.Get("userID")
	tickets, total, err := h.ticketService.ListAssignedTickets(userID.(uint), page, pageSize)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"code":    500,
			"message": "获取分配给我的工单列表失败: " + err.Error(),
		})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"code":    200,
		"message": "获取分配给我的工单列表成功",
		"data": gin.H{
			"tickets":    tickets,
			"total":      total,
			"page":       page,
			"page_size":  pageSize,
			"total_page": (total + int64(pageSize) - 1) / int64(pageSize),
		},
	})
}

// AssignTicket 分配工单
func (h *TicketHandler) AssignTicket(c *gin.Context) {
	var req struct {
		AssigneeID uint `json:"assignee_id" binding:"required"`
	}

	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{
			"code":    400,
			"message": "请求参数错误: " + err.Error(),
		})
		return
	}

	ticketIDStr := c.Param("id")
	ticketID, err := strconv.ParseUint(ticketIDStr, 10, 32)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{
			"code":    400,
			"message": "无效的工单ID",
		})
		return
	}

	ticket, err := h.ticketService.AssignTicket(uint(ticketID), req.AssigneeID)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{
			"code":    400,
			"message": "分配工单失败: " + err.Error(),
		})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"code":    200,
		"message": "工单分配成功",
		"data":    ticket,
	})
}

// TakeTicket 接手工单
func (h *TicketHandler) TakeTicket(c *gin.Context) {
	ticketIDStr := c.Param("id")
	ticketID, err := strconv.ParseUint(ticketIDStr, 10, 32)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{
			"code":    400,
			"message": "无效的工单ID",
		})
		return
	}

	// 获取用户ID和角色
	userID, _ := c.Get("userID")
	userRole, _ := c.Get("role")

	// 检查权限：只有客服/管理员可以接手工单
	if userRole != models.RoleSupport && userRole != models.RoleAdmin {
		c.JSON(http.StatusForbidden, gin.H{
			"code":    403,
			"message": "只有客服或管理员可以接手工单",
		})
		return
	}

	// 接手工单
	ticket, err := h.ticketService.TakeTicket(uint(ticketID), userID.(uint))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{
			"code":    400,
			"message": "接手工单失败: " + err.Error(),
		})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"code":    200,
		"message": "工单接手成功",
		"data":    ticket,
	})
}

// ResolveTicket 解决工单
func (h *TicketHandler) ResolveTicket(c *gin.Context) {
	ticketIDStr := c.Param("id")
	ticketID, err := strconv.ParseUint(ticketIDStr, 10, 32)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{
			"code":    400,
			"message": "无效的工单ID",
		})
		return
	}

	// 获取工单信息
	ticket, err := h.ticketService.GetTicketByID(uint(ticketID))
	if err != nil {
		c.JSON(http.StatusNotFound, gin.H{
			"code":    404,
			"message": "工单不存在: " + err.Error(),
		})
		return
	}

	// 检查权限：只有工单的分配者可以解决工单
	userID, _ := c.Get("userID")
	userRole, _ := c.Get("role")

	isAssignee := ticket.AssigneeID != nil && *ticket.AssigneeID == userID.(uint)
	isAdmin := userRole == models.RoleAdmin

	if !isAssignee && !isAdmin {
		c.JSON(http.StatusForbidden, gin.H{
			"code":    403,
			"message": "只有工单的分配者或管理员可以解决工单",
		})
		return
	}

	// 解决工单
	resolvedTicket, err := h.ticketService.ResolveTicket(uint(ticketID))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{
			"code":    400,
			"message": "解决工单失败: " + err.Error(),
		})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"code":    200,
		"message": "工单已解决",
		"data":    resolvedTicket,
	})
}

// CloseTicket 关闭工单
func (h *TicketHandler) CloseTicket(c *gin.Context) {
	ticketIDStr := c.Param("id")
	ticketID, err := strconv.ParseUint(ticketIDStr, 10, 32)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{
			"code":    400,
			"message": "无效的工单ID",
		})
		return
	}

	// 获取工单信息
	ticket, err := h.ticketService.GetTicketByID(uint(ticketID))
	if err != nil {
		c.JSON(http.StatusNotFound, gin.H{
			"code":    404,
			"message": "工单不存在: " + err.Error(),
		})
		return
	}

	// 检查权限：工单创建者、分配者或管理员可以关闭工单
	userID, _ := c.Get("userID")
	userRole, _ := c.Get("role")

	isCreator := ticket.CreatorID == userID.(uint)
	isAssignee := ticket.AssigneeID != nil && *ticket.AssigneeID == userID.(uint)
	isAdmin := userRole == models.RoleAdmin

	if !isCreator && !isAssignee && !isAdmin {
		c.JSON(http.StatusForbidden, gin.H{
			"code":    403,
			"message": "您没有权限关闭此工单",
		})
		return
	}

	// 关闭工单
	closedTicket, err := h.ticketService.CloseTicket(uint(ticketID))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{
			"code":    400,
			"message": "关闭工单失败: " + err.Error(),
		})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"code":    200,
		"message": "工单已关闭",
		"data":    closedTicket,
	})
}

// AddComment 添加工单评论
func (h *TicketHandler) AddComment(c *gin.Context) {
	var req struct {
		Content string `json:"content" binding:"required"`
	}

	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{
			"code":    400,
			"message": "请求参数错误: " + err.Error(),
		})
		return
	}

	ticketIDStr := c.Param("id")
	ticketID, err := strconv.ParseUint(ticketIDStr, 10, 32)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{
			"code":    400,
			"message": "无效的工单ID",
		})
		return
	}

	userID, _ := c.Get("userID")

	// 添加评论
	comment, err := h.ticketService.AddComment(uint(ticketID), userID.(uint), req.Content)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{
			"code":    400,
			"message": "添加评论失败: " + err.Error(),
		})
		return
	}

	c.JSON(http.StatusCreated, gin.H{
		"code":    201,
		"message": "评论添加成功",
		"data":    comment,
	})
}

// ListComments 获取工单评论列表
func (h *TicketHandler) ListComments(c *gin.Context) {
	ticketIDStr := c.Param("id")
	ticketID, err := strconv.ParseUint(ticketIDStr, 10, 32)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{
			"code":    400,
			"message": "无效的工单ID",
		})
		return
	}

	// 获取工单信息，检查是否存在
	_, err = h.ticketService.GetTicketByID(uint(ticketID))
	if err != nil {
		c.JSON(http.StatusNotFound, gin.H{
			"code":    404,
			"message": "工单不存在: " + err.Error(),
		})
		return
	}

	comments, err := h.ticketService.ListComments(uint(ticketID))
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"code":    500,
			"message": "获取评论列表失败: " + err.Error(),
		})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"code":    200,
		"message": "获取评论列表成功",
		"data":    comments,
	})
}

// GetTicketMetrics 获取工单统计信息
func (h *TicketHandler) GetTicketMetrics(c *gin.Context) {
	metrics, err := h.ticketService.GetTicketMetrics()
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"code":    500,
			"message": "获取工单统计信息失败: " + err.Error(),
		})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"code":    200,
		"message": "获取工单统计信息成功",
		"data":    metrics,
	})
} 